import { Vue, Component, Prop, Watch, Emit, Inject, InjectReactive, Model, Provide, PropSync } from 'vue-property-decorator'
import { myHeader } from '../myheader';

@Component({
  components: {
    myHeader
  },
  // mixins: [require('../minix/index.vue')]
})
export class mytable extends Vue {

  //属性
  @Prop(String) tableName?: string;
  @Prop({ default: '属性默认值' }) defaultName!: string;
  @Prop([String, Boolean]) choosevalue!: string | boolean;

  //私有页面变量
  private mytablename: string = '';
  //共有页面变量
  public componentName: string = '调用了子组件 componentName 属性';

  //监听；监听可以监听属性或者变量
  //监听属性
  @Watch('tableName')
  tablenameChange(n: string, o: string) {
    alert(n);
  }
  //监听属性
  @Watch('defaultName')
  defaultNameChange(n: string, o: string) {
    alert(`defaultName变成 ：${n}`);
  }
  //监听变量
  @Watch('mytablename')
  mytablenameChange(n: string, o: string) {
    alert(`mytablename变成 ：${n}`);
  }


  //子组件通过事件传递给父组件
  @Emit()
  emitChange(n: string) {
    //如果 emit 没有指定函数名称的话 父组件需要用 kebab-case 调用 即 on-emit-change 
    //如果指定了函数名称 则用函数名称
    alert('emitChange' + n);
  }

  @Emit('reset')
  emitTodo(n: string) {
    alert(n)
  }


  @Emit('emitTodoReset')
  emitTodoReset(n: string) {
    alert('emitTodoReset:' + n)
  }

  clickEmit() {
    this.emitTodo('abcd');
  }

  clickNoEmit() {
    this.emitChange('abcd');
  }

  clickEmitReset() {
    //子组件传递值给父组件
    this.emitTodoReset('abcd');
  }

  //注入
  @Inject({ from: 'providename' })
  injectName!: string;

  @Inject({ from: 'providenameDefault', default: 'abcd' })
  providenameDefault?: string;


  //生命周期
  beforeCreated() {
    //在实例初始化之后，数据观测和事件配置之前被调用，此时组件的选项对象还未创建，el 和 data 并未初始化，因此无法访问methods， data， computed等上的方法和数据。
  }
  created() {
    //实例已经创建完成之后被调用，在这一步，实例已完成以下配置：数据观测、属性和方法的运算，watch/event事件回调，完成了data 数据的初始化，el没有
  }
  beforeMount() {
    //挂在开始之前被调用，相关的render函数首次被调用（虚拟DOM），实例已完成以下的配置： 编译模板，把data里面的数据和模板生成html，完成了el和data 初始化，注意此时还没有挂在html到页面上

  }
  mounted() {
    //挂在完成，也就是模板中的HTML渲染到HTML页面中，此时一般可以做一些ajax操作，mounted只会执行一次
  }
  beforeUpdate() {
    //在数据更新之前被调用，发生在虚拟DOM重新渲染和打补丁之前，可以在该钩子中进一步地更改状态，不会触发附加地重渲染过程
  }
  updated() {
    //在由于数据更改导致地虚拟DOM重新渲染和打补丁只会调用，调用时，组件DOM已经更新，所以可以执行依赖于DOM的操作，然后在大多是情况下，应该避免在此期间更改状态，因为这可能会导致更新无限循环，该钩子在服务器端渲染期间不被调用

  }
  beforeDestroy() {
    //在实例销毁之前调用，实例仍然完全可用
    //这一步还可以用this来获取实例，
    //一般在这一步做一些重置的操作，比如清除掉组件中的定时器 和 监听的dom事件
  }
  destroyed() {
    //在实例销毁之后调用，调用后，所以的事件监听器会被移出，所有的子实例也会被销毁，该钩子在服务器端渲染期间不被调用
  }

  render() {
    return (
      <div>
        <p>属性</p>
        传入组件属性@Prop：tableName ；值是：{this.tableName} <br />
        传入组件默认值属性@Prop('{'default:\'属性默认值\''}') : 值是 {this.defaultName}<br />
        传入组件可选属性 @Prop([String,Boolean]) : 值是 {this.choosevalue.toString()}<br />
        <p>Watch</p>
        监听属性：defaultname ,value:{this.defaultName} <el-input v-model={this.defaultName} placeholder="请输入内容"></el-input><br />
        监听属性：mytablename,value:{this.mytablename} <el-input v-model={this.mytablename} placeholder="请输入内容"></el-input>
        <p>Emit</p>
        <el-button type="primary" on-click={this.clickEmit}>组件Emit(调用父组件)</el-button>
        <el-button type="primary" on-click={this.clickEmitReset}>组件emitTodoReset(调用父组件)</el-button>
        <el-button type="primary" on-click={this.clickNoEmit}>组件clickNoEmit(调用父组件)</el-button>

        <p>Provid/Inject;Provid 父组件提供向下的数据，子组件用Inject接收</p>
        inject 从父组件传递下来的值 :{this.injectName} <br />
        providenameDefault 父组件没有传递值 默认值：{this.providenameDefault}
        <myHeader></myHeader>
        <p>
          {this.$slots.header}
        </p>
      </div>
    );

  }
}
